package com.ds.infrastructure.audit.client.track;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.ds.infrastructure.audit.common.entity.KbaBehavior;
import com.ds.infrastructure.audit.common.entity.KbaBehaviorWrapper;
import com.ds.infrastructure.audit.common.exception.KbaAuditException;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

/**
 * 作用：
 *
 * @author WeiShaoying
 * @date 2020/7/27
 */
public abstract class AbstractKbaTrack implements KbaTrack {

    protected String server;

    protected String appName;

    protected String appKey;

    AbstractKbaTrack(String server) {
        this.server = server;
    }

    AbstractKbaTrack(String server, String appName, String appKey) {
        this.server = server;
        this.appName = appName;
        this.appKey = appKey;
    }

    /**
     * 初始化
     */
    public abstract void initialize();

    /**
     * 参数校验
     *
     * @param behavior
     */
    private void validate(KbaBehavior behavior) {
        if (behavior == null) {
            throw new KbaAuditException("参数behavior不能为空");
        }
        if (StrUtil.isBlank(appName) || StrUtil.isBlank(appKey)) {
            throw new KbaAuditException("appName,appKey不能为空");
        }
        String bizName = behavior.getBizName();
        String action = behavior.getAction();
        String actionDetail = behavior.getActionDetail();
        if (StringUtils.isBlank(bizName) || StringUtils.isBlank(action) || StringUtils.isBlank(behavior.getUserId())) {
            throw new KbaAuditException("bizName,userId,action不能为空");
        }
        if (bizName.length() > 20 || action.length() > 20 || actionDetail.length() > 500) {
            throw new KbaAuditException("bizName最大长度20个字符,action最大长度20个字符,actionDetail最大长度500个字符");
        }
        Map<String, String> extra = behavior.getExtra();
        if (MapUtil.isNotEmpty(extra) && extra.size() > 30) {
            throw new KbaAuditException("extra最多允许30个元素");
        }
    }

    /**
     * Convert
     *
     * @param behavior
     * @return
     */
    private KbaBehaviorWrapper getKbaBehaviorWrapper(KbaBehavior behavior) {
        KbaBehaviorWrapper wrapper = KbaBehaviorWrapper.of(behavior);
        wrapper.setAppName(appName);
        wrapper.setAppKey(appKey);
        return wrapper;
    }

    /**
     * Kba上报
     *
     * @param behavior
     * @throws KbaAuditException
     */
    @Override
    public void report(KbaBehavior behavior) throws KbaAuditException {
        validate(behavior);
        KbaBehaviorWrapper wrapper = getKbaBehaviorWrapper(behavior);
        report0(wrapper);
    }

    /**
     * 上报并指定回调处理
     *
     * @param behavior
     * @param callback
     * @throws KbaAuditException
     */
    @Override
    public void report(KbaBehavior behavior, KbaCallback callback) throws KbaAuditException {
        validate(behavior);
        report0(getKbaBehaviorWrapper(behavior), callback);
    }

    /**
     * Report Wrapper
     *
     * @param wrapper
     * @throws KbaAuditException
     */
    protected abstract void report0(KbaBehaviorWrapper wrapper) throws KbaAuditException;

    /**
     * Report Wrapper with callback
     *
     * @param wrapper
     * @param callback
     * @throws KbaAuditException
     */
    protected abstract void report0(KbaBehaviorWrapper wrapper, KbaCallback callback) throws KbaAuditException;

}
